/**
 * 
 */
package info.niwota.webagent;

import info.niwota.org.json.JSONObject;
import info.niwota.webagent.peer.ChannelManager;
import info.niwota.webagent.peer.Messenger;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.api.xmpp.JID;
import com.google.appengine.api.xmpp.Presence;
import com.google.appengine.api.xmpp.XMPPService;
import com.google.appengine.api.xmpp.XMPPServiceFactory;


/**
 * @author qiangli
 * 
 */
@SuppressWarnings("serial")
public class BaseServlet extends HttpServlet {
	private static final Logger log = Logger.getLogger(BaseServlet.class
			.getName());
	protected static final UserService userService = UserServiceFactory.getUserService();
	
	protected static final XMPPService xmpp = XMPPServiceFactory
			.getXMPPService();

	protected static final ChannelManager manager = ChannelManager
			.getInstance();

	protected static final String ERROR = "error";

	protected void sendMessage(HttpServletRequest req, HttpServletResponse res, String cmd, JSONObject data)
			throws ServletException, IOException {

		JSONObject json = new JSONObject();

		try {
			String peer = req.getParameter("peer");
			String uri = req.getRequestURI();			
			
			if (peer != null) {
				JID jid = new JID(peer);

				Presence p = xmpp.getPresence(jid, Messenger.APP_JID);

				if (p == null || !p.isAvailable()) {
					log.finest("Unavalable " + peer + ": " + p);

					json.put(ERROR, "Peer unavailable");

				} else {
					//send request
					
					String cid = req.getParameter("cid");
					String tag = req.getParameter("tag");
					
					data.put("uri", uri);
					data.put("q", rewriteQuery(req.getQueryString()));
					
					data.put("user", getCurrentUser());
					
					manager.send(peer, cid, tag, cmd, data);

					log.finest("peer online: " + p.getFromJid() + " status: "
							+ p.getStatus());

				}
			} else {
				json.put(ERROR, "Peer ID required");
			}

		} catch (Exception e) {
			log.log(Level.SEVERE, e.getMessage());
			
			try {
				json.put(ERROR, e.getLocalizedMessage());
			} catch (Exception e1) {
				log.log(Level.SEVERE, e1.getMessage());
			}
		}

		sendJSON(req, res, json);
	}

	private String rewriteQuery(String q) {
		//TODO filter out callback?
		return q;
	}

	protected String getCurrentUser() {
		User user = userService.getCurrentUser();
		return (user == null ? null : user.getEmail());
	}

	protected void sendJSON(HttpServletRequest req, HttpServletResponse res,
			JSONObject data) throws IOException {
		res.setContentType("application/json");
		PrintWriter out = res.getWriter();

		String callback = req.getParameter("callback");
		String js = null;
		if (isEmpty(callback)) {
			js = data.toString();
		} else {
			js = callback + "(" + data.toString() + ")";
		}
		out.println(js);
		
		log.finest("json: " + js);
	}
	
	protected int parseInt(String s, int defval) {
		try {
			return Integer.parseInt(s);
		} catch (Exception e) {

		}
		return defval;
	}

	protected long parseLong(String s, long defval) {
		try {
			return Long.parseLong(s);
		} catch (Exception e) {

		}
		return defval;
	}

	protected boolean isEmpty(String s) {
		return (s == null || s.equals(""));
	}
	
	protected String query(HttpServletRequest req) {
		String q = req.getQueryString();
		return (q == null ? "" : "?" + q);
	}
	
	protected void sendError(HttpServletRequest req, HttpServletResponse resp, String msg) throws IOException {
		resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
	}
	
	protected void forward(HttpServletRequest req, HttpServletResponse resp, String uri) throws ServletException, IOException {
		RequestDispatcher dispatch = req.getRequestDispatcher(uri);
		dispatch.forward(req, resp);
	}
}
